package com.frejoys.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frejoys.common.dto.common.auth.AuthRuleAddDto;
import com.frejoys.common.dto.common.auth.AuthRuleUpDto;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.common.vo.common.auth.AuthRuleMenuVo;
import com.frejoys.common.vo.common.auth.AuthRuleVo;
import com.frejoys.dao.entity.AuthRule;
import com.frejoys.dao.mapper.AuthRuleMapper;
import com.frejoys.service.AuthGroupService;
import com.frejoys.service.AuthRuleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class AuthRuleServiceImpl extends ServiceImpl<AuthRuleMapper, AuthRule> implements AuthRuleService {

    private final AuthGroupService authGroupService;

    @Override
    public boolean addInfo(AuthRuleAddDto dto) {
        Integer authId = getIdByRoute(dto.getRoute());
        if (authId != null) {
            throw new GeneralException(HttpStatus.ruleAlreadyExist);
        }

        String path = "0";
        if (!dto.getPid().equals(0)) {
            AuthRule pAR = getInfo(dto.getPid());
            path = pAR.getPath() + "," + pAR.getId();
        }

        String finalPath = path;

        return save(new AuthRule(){{
            setIcon(dto.getIcon());
            setRoute(dto.getRoute());
            setName(dto.getName());
            setPid(dto.getPid());
            setPath(finalPath);
            setSort(dto.getSort() == null ? 0 : dto.getSort());
        }});
    }

    @Override
    public boolean upInfo(AuthRuleUpDto dto) {
        Integer authId = getIdByRoute(dto.getRoute());
        if (authId != null) {
            throw new GeneralException(HttpStatus.ruleAlreadyExist);
        }

        LambdaUpdateWrapper<AuthRule> wrapper = new UpdateWrapper().lambda();
        wrapper.eq(AuthRule::getId, dto.getId());

        if (StrUtil.isNotEmpty(dto.getIcon())) {
            wrapper.set(AuthRule::getIcon, dto.getIcon());
        }

        if (StrUtil.isNotEmpty(dto.getRoute())) {
            wrapper.set(AuthRule::getRoute, dto.getRoute());
        }

        if (StrUtil.isNotEmpty(dto.getName())) {
            wrapper.set(AuthRule::getName, dto.getName());
        }

        if (dto.getSort() != null) {
            wrapper.set(AuthRule::getSort, dto.getSort());
        }

        if (dto.getPid() != null) {
            // 判断
            if (dto.getPid().equals(0)) {
                wrapper.set(AuthRule::getPid, dto.getPid());
                wrapper.set(AuthRule::getPath, dto.getPid());
            } else {

                // pid和原pid是否一致
                LambdaQueryWrapper<AuthRule> sAuth = new QueryWrapper().lambda();
                sAuth.select(AuthRule::getPid).eq(AuthRule::getId, dto.getId());
                AuthRule sAR = getOnly(sAuth);
                if (!dto.getPid().equals(sAR.getPid())) {
                    // 新pid
                    LambdaQueryWrapper<AuthRule> nAuth = new QueryWrapper().lambda();
                    nAuth.select(AuthRule::getPath).eq(AuthRule::getId, dto.getPid());
                    AuthRule nAR = getOnly(nAuth);
                    wrapper.set(AuthRule::getPid, dto.getPid());
                    wrapper.set(AuthRule::getPath, nAR.getPath() + "," + dto.getPid());
                }

            }
        }

        return update(wrapper);
    }

    @Override
    public AuthRule getInfo(Integer id) {
        LambdaQueryWrapper<AuthRule> wrapper = new QueryWrapper().lambda();
        wrapper.eq(AuthRule::getId, id);
        return getOnly(wrapper);
    }

    @Override
    public Integer getIdByRoute(String route) {
        LambdaQueryWrapper<AuthRule> wrapper = new QueryWrapper().lambda();
        wrapper.select(AuthRule::getId).eq(AuthRule::getRoute, route);
        AuthRule rule = getOnly(wrapper);
        return rule != null ? rule.getId() : null;
    }

    @Override
    public List<AuthRuleVo> listInfo(Long userId) {
        List<AuthRuleVo> list = new ArrayList<>();

        LambdaQueryWrapper<AuthRule> wrapper = new QueryWrapper().lambda();
        List<AuthRule> authRules = list(wrapper);

        // 获取用户权限
        List<String> rules = new ArrayList<>();

        if (userId != null) {
            rules = authGroupService.listUserGroupRules(userId);
        }

        for (AuthRule e : authRules) {
            AuthRuleVo vo = new AuthRuleVo();
            BeanUtil.copyProperties(e, vo);

            if (rules.contains(vo.getId().toString())) {
                vo.setIsRule(true);
            } else {
                vo.setIsRule(false);
            }

            list.add(vo);
        }

        return list;
    }

    @Override
    public List<AuthRule> getListByPidOrder(Integer pid) {
        LambdaQueryWrapper<AuthRule> wrapper = new QueryWrapper().lambda();
        wrapper.eq(AuthRule::getPid, pid).orderByAsc(AuthRule::getSort);
        return list(wrapper);
    }

    @Override
    public List<AuthRule> getListByPidOrder(List<Integer> pid) {
        LambdaQueryWrapper<AuthRule> wrapper = new QueryWrapper().lambda();
        wrapper.in(AuthRule::getPid, pid).orderByAsc(AuthRule::getSort);
        return list(wrapper);
    }

    @Override
    public List<AuthRuleMenuVo> listMenu(Long userId) {
        List<AuthRuleMenuVo> list = new ArrayList<>();

        // 查询主菜单
        List<AuthRule> rules = getListByPidOrder(0);

        if (!rules.isEmpty()) {

            // 过滤无权限主菜单
            List<AuthRule> filterRule = authGroupService.filterRule(userId, rules);

            if (!filterRule.isEmpty()) {
                // 查询二级菜单
                List<Integer> subIds = filterRule.stream().map(e -> e.getId()).collect(Collectors.toList());
                List<AuthRule> subList = getListByPidOrder(subIds);
                Map<Integer, List<AuthRule>> subMap = new HashMap<>();
                subList.forEach( e -> {
                    if (subMap.get(e.getPid()) == null) {
                        List<AuthRule> tmpList = new ArrayList<>();
                        tmpList.add(e);
                        subMap.put(e.getPid(), tmpList);
                    } else {
                        subMap.get(e.getPid()).add(e);
                    }
                });

                if (!subMap.isEmpty()) {
                    filterRule.forEach( e -> {
                        AuthRuleMenuVo vo = new AuthRuleMenuVo();
                        BeanUtil.copyProperties(e, vo);

                        // 组装二级菜单
                        List<AuthRuleVo> subTmp = new ArrayList<>();
                        if (subMap.get(e.getId()) != null) {
                            List<AuthRule> subListRuleVo = subMap.get(e.getId());
                            subListRuleVo.forEach( ev -> {
                                AuthRuleVo subuleVo = new AuthRuleVo();
                                BeanUtil.copyProperties(ev, subuleVo);
                                subTmp.add(subuleVo);
                            });
                        }

                        vo.setSubList(subTmp);
                        list.add(vo);
                    });
                }

            }

        }

        return list;
    }

    @Override
    public boolean authCheck(Long userId, String route) {
        // 获取用户权限
        List<String> rules = authGroupService.getUserGroupRules(userId);

        if (!rules.isEmpty()) {
            // 获取当前路径信息
            Integer id = getIdByRoute(route);
            if (id != null && rules.contains(id.toString())) {
                return true;
            }
        }

        return false;
    }


    @Override
    public List<AuthRuleMenuVo> listAll() {

        List<AuthRuleMenuVo> list = new ArrayList<>();

        // 查询主菜单
        List<AuthRule> rules = getListByPidOrder(0);

        if (!rules.isEmpty()){

            // 查询二级菜单
            List<Integer> subIds = rules.stream().map(e -> e.getId()).collect(Collectors.toList());
            List<AuthRule> subList = getListByPidOrder(subIds);
            Map<Integer, List<AuthRule>> subMap = new HashMap<>();

            subList.forEach( e -> {
                if (subMap.get(e.getPid()) == null) {
                    List<AuthRule> tmpList = new ArrayList<>();
                    tmpList.add(e);
                    subMap.put(e.getPid(), tmpList);
                } else {
                    subMap.get(e.getPid()).add(e);
                }
            });

            if (!subMap.isEmpty()) {
                rules.forEach( e -> {
                    AuthRuleMenuVo vo = new AuthRuleMenuVo();
                    BeanUtil.copyProperties(e, vo);

                    // 组装二级菜单
                    List<AuthRuleVo> subTmp = new ArrayList<>();
                    if (subMap.get(e.getId()) != null) {
                        List<AuthRule> subListRuleVo = subMap.get(e.getId());
                        subListRuleVo.forEach( ev -> {
                            AuthRuleVo subuleVo = new AuthRuleVo();
                            BeanUtil.copyProperties(ev, subuleVo);
                            subTmp.add(subuleVo);
                        });
                    }

                    vo.setSubList(subTmp);
                    list.add(vo);
                });
            }
        }
        return list;
    }

}
